package learnjava.basic.other;

import java.lang.annotation.*;
import java.lang.reflect.Method;

@MyAnno2(className = "learnjava.basic.other.AClass",methodName = "show1")
public class TestAnnotation {

    public static void main(String[] args) throws Exception{
        //1，解析注解
        //1.1获取该类的字节码文件对象
        Class testAnnotationClass = TestAnnotation.class;
        //2，获取上边的注解对象，下面这行代码其实就是在内存中生成了一个该注解类型的子类实现对象
        MyAnno2 an = (MyAnno2) testAnnotationClass.getAnnotation(MyAnno2.class);
        //3，调用注解对象中定义的抽象方法，获取返回值
        String className = an.className();
        String methodName = an.methodName();
        //4，使用方法
        Class target = Class.forName(className);
        Object o = target.getConstructor().newInstance();
        Method m = target.getMethod(methodName);
        m.invoke(o);
        //调用添加了注解的方法
        new TestAnnotation().testAnnoOnMethod();
    }

    /**
        * @param
        * @return void
        * @desc testAnnoOnMethod，测试定义在方法上的注解
    */
    @MyAnno2(className = "learnjava.basic.other.AClass",methodName = "show2")
    public void testAnnoOnMethod () throws Exception{
        //1，解析注解
        //1.1获取该类的字节码文件对象
        Class testAnnotationClass = TestAnnotation.class;
        //2, 获取testAnnoOnMethod方法上的注解对象
        Method method = testAnnotationClass.getMethod("testAnnoOnMethod");
        MyAnno2 an = (MyAnno2)method.getAnnotation(MyAnno2.class);
        //3，调用注解对象中定义的抽象方法，获取返回值
        String className = an.className();
        String methodName = an.methodName();
        //4，使用方法
        Class target = Class.forName(className);
        Object o = target.getConstructor().newInstance();
        Method m = target.getMethod(methodName);
        m.invoke(o);
    }
}

/**
    * @author wangc
    * @date 2021/6/16 下午 9:42
    * 一个通过传入全类名和方法执行的注解
*/
@Target(value = {ElementType.METHOD,ElementType.TYPE})
@Retention(value = RetentionPolicy.RUNTIME)
@Inherited
@interface MyAnno2{
    String className();
    String methodName();
}


/**
    * @author wangc
    * @date 2021/6/16 下午 9:39
    * 一个普通类
*/
class AClass{

    public AClass(){};

    public void show1(){
        System.out.println("AClass show1");
    }
    public void show2(){
        System.out.println("AClass show2");
    }
}



/**
    * @author wangc
    * @date 2021/6/16 下午 9:41
    * 定义一个注解的基本语法
*/
//先写元注解
//Target表示注解可以用在那些地方
@Target(value = {ElementType.METHOD,ElementType.TYPE})
//Retention定义注解作用范围
@Retention(value = RetentionPolicy.RUNTIME)
//是否将注解生成到JAVADoc中
@Documented
//子类可以继承父类的注解
@Inherited
@interface MyAnno1{
    //注解的参数：参数类型+参数名
    String name() default "";
    int age() default 0;
    int id() default -1;
    String[] strings() default {};
}



